package net.takela.common.webflux.security.exception;

import net.takela.common.spring.exception.StatusCodeException;
import net.takela.common.spring.http.HttpResponse;
import net.takela.common.spring.http.StatusCode;
import net.takela.common.spring.message.MessageSource;
import net.takela.common.utils.JSONUtils;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.ConnectException;
import java.nio.charset.StandardCharsets;

/**
 * @author zhangyinghui
 * create at 2023/7/11
 */
//@Component
public class AppSecurityExceptionHandler implements ErrorWebExceptionHandler {
    /**
     * 
     */
    public Object handleError(ServerWebExchange exchange, Throwable ex){
        return null;
    }
    
    /**
     * 
     */
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ex.printStackTrace();
        Object r = handleError(exchange, ex);
        if (r == null) {
            if (ex instanceof ResponseStatusException) {
                ResponseStatusException e = (ResponseStatusException) ex;
                r = new HttpResponse<>(e.getStatusCode().value(), e.getReason());
            } else if (ex instanceof ConnectException) {
                r = HttpResponse.error(StatusCode.ERROR.getCode(), MessageSource.getMessage("network.conn.exception.desc", ex.getLocalizedMessage()));
            } else if(ex instanceof StatusCodeException){
                r = HttpResponse.error(((StatusCodeException) ex).getCode(), ((StatusCodeException) ex).getMessage());
            }else {
                r = new HttpResponse<>(HttpStatus.FORBIDDEN.value(), HttpStatus.FORBIDDEN.getReasonPhrase());
            }
        }
        Object ret = r;
        return exchange.getResponse().writeWith(Mono.fromSupplier(()->{
            DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
            try {
                return bufferFactory.wrap(JSONUtils.toString(ret).getBytes(StandardCharsets.UTF_8))
;            }catch (Exception e){
                return bufferFactory.wrap(new byte[0]);
            }
        }));
    }
}
